package com.xuantian.baoming.service.Impl;

import com.google.gson.Gson;
import com.xuantian.baoming.config.wxPayConfig;
import com.xuantian.baoming.entity.OrderInfo;
import com.xuantian.baoming.enums.OrderStatus;
import com.xuantian.baoming.enums.wxpay.WxApiType;
import com.xuantian.baoming.enums.wxpay.WxNotifyType;
import com.xuantian.baoming.service.OrderInfoService;
import com.xuantian.baoming.service.PaymentInfoService;
import com.xuantian.baoming.service.WxH5Service;
import com.xuantian.baoming.util.OrderNoUtils;
import com.xuantian.baoming.util.UserAgentUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

@Service
@Slf4j
public class WxH5ServiceImpl implements WxH5Service {

    @Autowired
    private CloseableHttpClient wxPayClient;

    @Autowired
    private com.xuantian.baoming.config.wxPayConfig wxPayConfig;

    @Autowired
    private OrderInfoService orderInfoService;

    @Autowired
    private PaymentInfoService paymentInfoService;

    private final ReentrantLock lock = new ReentrantLock();

    @Value("${totalFee}")
    private Integer totalFee;
    @Override
    public Map<String, Object> h5Pay(HttpServletRequest request,OrderInfo orderInfo1) throws Exception{
        log.info("h5支付");
        log.info("生成订单");

        orderInfo1.setOrderNo(OrderNoUtils.getOrderNo());//订单号
        orderInfo1.setStatus(OrderStatus.NOTPAY.getType());//支付状态
        orderInfo1.setTotalFee(totalFee);//金额

        //生成订单
        OrderInfo orderInfo = orderInfoService.createOrder(orderInfo1);

        HttpPost httpPost = new HttpPost(wxPayConfig.getDomain().concat(WxApiType.H5_PAY.getType()));

        // 请求body参数
        Gson gson = new Gson();
        Map paramsMap = new HashMap();
        paramsMap.put("appid", wxPayConfig.getAppid());
        paramsMap.put("mchid", wxPayConfig.getMchId());
        paramsMap.put("description", "诗词比赛报名费");
        paramsMap.put("out_trade_no", orderInfo.getOrderNo());
        paramsMap.put("notify_url", wxPayConfig.getNotifyDomain().concat(WxNotifyType.H5_NOTIFY.getType()));
        Map amountMap = new HashMap();
        amountMap.put("total", orderInfo.getTotalFee());
        amountMap.put("currency", "CNY");
        paramsMap.put("amount", amountMap);

        HashMap h5InfoMap = new HashMap();
        h5InfoMap.put("type", UserAgentUtil.getDeviceType(request));
        HashMap sceneInfoMap = new HashMap();
        sceneInfoMap.put("payer_client_ip", UserAgentUtil.getClientIp(request));
        sceneInfoMap.put("h5_info", h5InfoMap);

        paramsMap.put("scene_info", sceneInfoMap);



        //将参数转换成json字符串
        String jsonParams = gson.toJson(paramsMap);
        log.info("请求参数 ===> {}" + jsonParams);


        StringEntity entity = new StringEntity(jsonParams,"utf-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "application/json");

        //完成签名并执行请求
        CloseableHttpResponse response = wxPayClient.execute(httpPost);

        String body = EntityUtils.toString(response.getEntity());

        try {
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 200) { //处理成功
                log.info("success,return body = " + body);
            } else if (statusCode == 204) { //处理成功，无返回Body
                log.info("success");
            } else {
                log.info("失败,resp code = " + statusCode+ ",return body = " + body);
                throw new IOException("request failed");
            }

            Map<String,String> resultMap = gson.fromJson(body, Map.class);
            String codeUrl = resultMap.get("h5_url");
            Map<String, Object> map = new HashMap<>();
            map.put("codeUrl",codeUrl);
            map.put("orderNo",orderInfo.getOrderNo());

            //todo codeUrl 存储到redis中 比较合理。如果 存在mysql中，要考虑 codeUrl 两小时后过期，
            //现在每一次都重新获取codeUrl 不做存储。
            return map;
        } finally {
            response.close();
        }
    }
}
